#include "led.h"

typedef struct
{
    uint32_t CRL;
    uint32_t CRH;
    uint32_t IDR;
    uint32_t ODR;
} GPIO_t;

// #define pGPIOB ((GPIO_t *)(0x40010C00))
/**
 * 实现LED的GPIO的初始化（配置为输出推挽模式）
 */
void led_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE(); // 开启GPIOB的时钟

    // // 配置GPIOB.0为输出模式
    // uint32_t *pCRL = (uint32_t *)(0x40010C00 + 0x00);

    // *pCRL &= ~(0xF << 0); // 最好进行先清除需要设置的位
    // *pCRL |= (0x03 << 0); // 设置为推挽输出模式

    // 同对寄存器进行封装（封装成一个完整的结构体）
    // GPIO_t *pGPIOB = (GPIO_t *)(0x40010C00);

    // pGPIOB->CRL &= ~(0xF << 0);
    // pGPIOB->CRL |= (0x03 << 0);

    // GPIOB->CRL &= ~(0xF << 0); // 直接使用STM32定义好的寄存器结构体，直接对寄存器进行操作
    // GPIOB->CRL |= (0x03 << 0);

    GPIO_InitTypeDef GPIO_InitTypeStrcuture = {0};

    GPIO_InitTypeStrcuture.Pin = GPIO_PIN_0;             // 选择PIN脚
    GPIO_InitTypeStrcuture.Mode = GPIO_MODE_OUTPUT_PP;   // 推挽输出模式
    GPIO_InitTypeStrcuture.Speed = GPIO_SPEED_FREQ_HIGH; // 输出速度
    // GPIO_InitTypeStrcuture.Pull = GPIO_NOPULL;           // 输出模式下，上下拉的状态是可以不用处理的

    HAL_GPIO_Init(GPIOB, &GPIO_InitTypeStrcuture);
}

/**
 * 实现LED状态翻转的函数
 */
void led_toggle(void)
{
    // 需要如何通过寄存器，来操作GPIOB.0,实现状态翻转？？？？
    // 1.找到GPIOB的ODR寄存器在地址总线中的位置
    // uint32_t *pODR = (uint32_t *)(0x40010C00 + 0x0C);

    // if ((*pODR) & (1 << 0))
    // {
    //     *pODR &= ~(1 << 0); // 让ODR bit0 输出低电平
    // }
    // else
    // {
    //     *pODR |= (1 << 0); // 让ODR bit0 输出高电平
    // }
    // HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);

    // if (GPIOB->ODR & (1 << 0))
    // {
    //     // GPIOB->ODR &= ~(1 << 0);
    //     GPIOB->BRR |= (1 << 0); // 也可以通过BRR寄存器对指定的ODR位进行清除
    // }
    // else
    // {
    //     GPIOB->BSRR |= (1 << 0); // 也可以通过BSRR寄存器对指定的ODR位进行置位
    //     // GPIOB->ODR |= (1 << 0);
    // }

    // 使用HAL可以直接完成以上操作
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
}